package com.qin.entity.components;

import com.qin.common.RegexProcessor;
import com.qin.db.Connector;
import com.qin.entity.ExecuteBean;
import com.qin.entity.ExecuteLog;
import com.qin.entity.SubComponent;
import com.qin.service.ExecuteService;
import com.qin.service.impl.ExecuteServiceImpl;

import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class DatabaseComponent {

    //组件ID
    private String component_id;
    //系统名称
    private String system_name;
    //输入SQL
    private String input_sql;
    //子组件列表
    private List<SubComponent> subComponentList;

    //是否执行子组件标志位（true-执行，false-不执行）
    private boolean exec_subCom_flag;
    //是否打印日志（true-打印，false-不打印）
    private boolean print_log_flag;

    private ExecuteService executeService = new ExecuteServiceImpl();

    public DatabaseComponent(String component_id, String system_name, String input_sql, List<SubComponent> subComponentList,
                             boolean exec_subCom_flag, boolean print_log_flag) {
        this.component_id = component_id;
        this.system_name = system_name;

        //左右去空格，去除末尾的分号;
        if(input_sql.trim().endsWith(";")){
            this.input_sql = input_sql.trim().substring(0, input_sql.trim().lastIndexOf(";")).trim();
        }else{
            this.input_sql = input_sql.trim();
        }

        this.subComponentList = subComponentList;

        this.exec_subCom_flag = exec_subCom_flag;
        this.print_log_flag = print_log_flag;
    }

    public void execute(ExecuteBean executeBean){

        Map retMap = new HashMap();

        //补全executeBean对象的各属性
        executeBean.setSystem_name(system_name);
        executeBean.complete();
        //设置ExecuteLog对象的各属性
        ExecuteLog executeLog = new ExecuteLog(executeBean.getExecute_id(), executeBean.getFunction_id(),
                executeBean.getTestcase_id(), executeBean.getComponent_id(), "", "");

        //--------------------执行组件--------------------
        RegexProcessor regexProcessor = new RegexProcessor();
        //替换input_sql中的#{xxx}为实际值
        input_sql = regexProcessor.replaceStringByMap(input_sql, executeBean.getParaMap());
        if(print_log_flag){
            //插入日志
            executeService.insertExecuteLog(executeLog, "【执行环境】系统："+executeBean.getSystem_name()+"，数据库："+executeBean.getDatabase_sid()+"库");
            executeService.insertExecuteLog(executeLog, "【执行SQL】" + input_sql);
        }

        //提取数据库ip和port
        String ip = regexProcessor.getStringByRegex(executeBean.getDatabase_string(), "\\([Hh][Oo][Ss][Tt]=(.+?)\\)").get(0).trim();
        String port = regexProcessor.getStringByRegex(executeBean.getDatabase_string(), "\\([Pp][Oo][Rr][Tt]=(.+?)\\)").get(0).trim();

        //拼接数据库url
        //jdbc:oracle:thin:@192.168.0.104:1521/XEPDB1
        String url = "jdbc:oracle:thin:@" + ip + ":" + port + "/" + executeBean.getDatabase_sid();


        Connector connector = null;
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;

        try {
            //----------数据库连接----------
            //创建Connector
            connector = new Connector(url, executeBean.getDatabase_username(), executeBean.getDatabase_password());
            //获取Connection
            connection = connector.getConnection();
            //创建PreparedStatement
            preparedStatement = connection.prepareStatement(input_sql);

            //----------执行select语句----------
            if(input_sql.toLowerCase().startsWith("select")){

                resultSet = preparedStatement.executeQuery();

                if(print_log_flag){
                    //插入日志
                    executeService.insertExecuteLog(executeLog, "----------select语句查询结果----------");
                }
                //获取查询结果queryResultList
                List<Map> queryResultList = new ArrayList<Map>();
                while(resultSet.next()){

                    //定义rowMap<列名, 查询结果值>
                    Map<String, String> rowMap = new HashMap<String, String>();

                    for(int i=1; i<=resultSet.getMetaData().getColumnCount(); i++){
                        //把每一行记录放入rowMap<列名, 查询结果值>中
                        rowMap.put(resultSet.getMetaData().getColumnName(i), resultSet.getObject(i).toString());
                    }

                    //把rowMap<列名, 查询结果值>加到resultList中
                    queryResultList.add(rowMap);
                }

                //打印查询结果resultList
                if(print_log_flag){
                    for(int i=0; i<queryResultList.size(); i++){
                        //插入日志
                        executeService.insertExecuteLog(executeLog, "【第"+i+"行】" + queryResultList.get(i));
                    }
                }

                //把queryResultList添加到executeBean的dbQueryResultMap中
                executeBean.getDbQueryResultMap().put(component_id, queryResultList);
            }
            //----------执行insert语句----------
            else if(input_sql.toLowerCase().startsWith("insert")){

                int count = preparedStatement.executeUpdate();

                if(print_log_flag){
                    System.out.println("----------insert语句执行结果----------");
                    System.out.println(count + "行记录被插入");
                }

            }
            //----------执行delete语句----------
            else if(input_sql.toLowerCase().startsWith("delete")){

                int count = preparedStatement.executeUpdate();

                if(print_log_flag){
                    System.out.println("----------delete语句执行结果----------");
                    System.out.println(count + "行记录被删除");
                }

            }
            //----------执行update语句----------
            else if(input_sql.toLowerCase().startsWith("update")){

                int count = preparedStatement.executeUpdate();

                if(print_log_flag){
                    System.out.println("----------update语句执行结果----------");
                    System.out.println(count + "行记录被更新");
                }
            }
        }
        catch (SQLException e){
            e.printStackTrace();
        }
        finally {
            connector.closeConnection(connection, preparedStatement, resultSet);
        }

        //--------------------遍历执行子组件--------------------
        if(exec_subCom_flag == true){
            if(subComponentList != null && subComponentList.size() > 0){
                for(int i=0; i<subComponentList.size(); i++){
                    subComponentList.get(i).execute(executeBean);
                }
            }
        }

    }
}
